<template>
  <div class="min-h-screen bg-gray-100 flex flex-col">
    <header class="bg-blue-600 text-white p-4 shadow-md">
      <div class="container mx-auto flex justify-between items-center">
        <h1 class="text-xl font-bold">CornerstoneJS 医学影像查看器</h1>
      </div>
    </header>

    <main class="flex-1 container mx-auto p-4">
      <div class="bg-white p-4 rounded-lg shadow-md mb-4">
        <div class="flex flex-col md:flex-row gap-4 items-center">
          <div class="flex-1">
            <label for="imageUrl" class="block text-sm font-medium text-gray-700 mb-1">DICOM 影像 URL</label>
            <input
                type="text"
                id="imageUrl"
                v-model="imageUrl"
                placeholder="https://example.com/image.dcm"
                class="w-full px-3 py-2 border border-gray-300 rounded-md"
            />
          </div>
          <div class="flex items-end gap-2">
            <button
                @click="loadImage"
                :disabled="isLoading"
                class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 flex items-center"
            >
              <span v-if="isLoading" class="animate-spin mr-2">⚙️</span>
              加载影像
            </button>
            <button
                @click="showInstructions = true"
                class="px-4 py-2 bg-green-600 text-white rounded-md hover:bg-green-700"
                title="查看工具使用说明"
            >
              ℹ️ 使用说明
            </button>
          </div>
        </div>
        <div v-if="errorMessage" class="mt-3 text-red-600">{{ errorMessage }}</div>
      </div>

      <div class="bg-white p-4 rounded-lg shadow-md">
        <div class="flex gap-4">
          <div class="w-64 space-y-2">
            <button @click="resetViewport" class="w-full bg-gray-200 rounded p-2">恢复原图</button>
            <button @click="activatePanTool" class="w-full bg-gray-200 rounded p-2">平移</button>
            <button @click="activateWwwcTool" class="w-full bg-gray-200 rounded p-2">对比度</button>
            <button @click="activateLengthTool" class="w-full bg-gray-200 rounded p-2">测量长度</button>
            <button @click="activateProbeTool" class="w-full bg-gray-200 rounded p-2">探针</button>
            <button @click="activateStackScrollTool" class="w-full bg-gray-200 rounded p-2">堆栈滚动</button>
            <button @click="activateAngleTool" class="w-full bg-gray-200 rounded p-2">角度测量</button>
            <button @click="activateEllipseTool" class="w-full bg-gray-200 rounded p-2">椭圆 ROI</button>
            <button @click="activateCircleROITool" class="w-full bg-gray-200 rounded p-2">圆形 ROI</button>
            <button @click="activateZoomTool" class="w-full bg-gray-200 rounded p-2">放大/缩小</button>
          </div>
          <div class="flex-1">
            <div class="w-full border rounded overflow-hidden">
              <div id="cornerstoneViewport" class="w-full h-full bg-black"></div>
            </div>
          </div>
        </div>
      </div>
    </main>

    <footer class="bg-gray-800 text-white p-4 text-center">
      <p>© 2024 CornerstoneJS Vue 3 医学影像查看器</p>
    </footer>

    <transition name="fade">
      <div
          v-if="showInstructions"
          class="fixed inset-0 bg-black bg-opacity-50 flex justify-center items-center z-50"
          @click.self="showInstructions = false"
      >
        <div class="bg-white rounded-lg shadow-lg max-w-lg w-full p-6 relative">
          <button
              @click="showInstructions = false"
              class="absolute top-2 right-2 text-gray-600 hover:text-gray-900 text-xl font-bold"
              aria-label="关闭"
          >
            &times;
          </button>
          <h2 class="text-2xl font-bold mb-4">工具使用说明</h2>
          <ul class="list-disc pl-5 space-y-2 text-gray-700">
            <li><strong>对比度</strong>：左键拖动调整图像对比度和亮度</li>
            <li><strong>缩放</strong>：左键拖动放大缩小</li>
            <li><strong>平移工具</strong>：左键拖动图像进行平移</li>
            <li><strong>测量长度工具</strong>：左键设置测量点，右键点击删除</li>
            <li><strong>探针工具</strong>：左键点击查看像素值，右键删除</li>
            <li><strong>堆栈滚动工具</strong>：左键拖动切换切片</li>
            <li><strong>角度测量</strong>：左键点击三点测角，右键删除</li>
            <li><strong>椭圆 ROI</strong>：左键绘制椭圆区域，右键删除</li>
            <li><strong>圆形 ROI</strong>：左键绘制圆形区域，右键删除</li>
          </ul>
        </div>
      </div>
    </transition>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted, nextTick } from 'vue';
import {
  RenderingEngine,
  init,
  Enums as CoreEnums,
} from '@cornerstonejs/core';
import {
  init as toolInit,
  PanTool,
  ProbeTool,
  ZoomTool,
  LengthTool,
  ToolGroupManager,
  Enums,
  WindowLevelTool,
  StackScrollTool,
  addTool,
  AngleTool,
  EllipticalROITool,
  CircleROITool,
} from '@cornerstonejs/tools';
import dicomImageLoader from '@cornerstonejs/dicom-image-loader';

const { ViewportType } = CoreEnums;
const { MouseBindings } = Enums;

const imageUrl = ref('');
const isLoading = ref(false);
const errorMessage = ref('');
const showInstructions = ref(false);

let renderingEngine: RenderingEngine | null = null;
const viewportId = 'DICOM_VIEWPORT';
const toolGroupId = 'IMAGE_TOOL_GROUP';

const toolNames = [
  WindowLevelTool.toolName,
  ZoomTool.toolName,
  PanTool.toolName,
  LengthTool.toolName,
  ProbeTool.toolName,
  StackScrollTool.toolName,
  AngleTool.toolName,
  EllipticalROITool.toolName,
  CircleROITool.toolName,
];

const initializeCornerstone = async () => {
  try {
    await init();
    await toolInit();
    await dicomImageLoader.init();

    [
      PanTool,
      ZoomTool,
      LengthTool,
      ProbeTool,
      WindowLevelTool,
      StackScrollTool,
      AngleTool,
      EllipticalROITool,
      CircleROITool,
    ].forEach(addTool);

    renderingEngine = new RenderingEngine('MAIN_RENDERING_ENGINE');

    await nextTick();
    const viewportElement = document.getElementById('cornerstoneViewport');
    if (!viewportElement || viewportElement.offsetHeight === 0) {
      throw new Error(`Viewport 尺寸不正确: ${viewportElement?.offsetWidth ?? 0}x${viewportElement?.offsetHeight ?? 0}`);
    }

    renderingEngine.enableElement(<any>{
      element: viewportElement,
      viewportId,
      type: ViewportType.STACK,
      defaultOptions: { background: [0.1, 0.1, 0.1] },
    });

    const toolGroup = ToolGroupManager.createToolGroup(toolGroupId);
    toolGroup.addViewport(viewportId, renderingEngine.id);

    toolNames.forEach((toolName) => {
      toolGroup.addTool(toolName);
    });

    // 默认激活平移工具，左键拖动
    setActiveTool(PanTool.toolName, MouseBindings.Primary);
  } catch (e: any) {
    console.error('Cornerstone 初始化失败:', e);
    errorMessage.value = `初始化失败: ${e.message}`;
  }
};

function getToolGroup() {
  return ToolGroupManager.getToolGroup(toolGroupId);
}

const clearToolActivation = () => {
    const toolGroup = getToolGroup();
  if (!toolGroup) return;

  toolNames.forEach(toolName => {
    toolGroup.setToolDisabled(toolName);
  });
};

const setActiveTool = (toolName: string, mouseButton: number) => {
  clearToolActivation();
  const toolGroup = getToolGroup();
  if (!toolGroup) return;

  toolGroup.setToolActive(toolName, {
    bindings: [{ mouseButton }],
  });

  renderingEngine?.render();
};

const loadImage = async () => {
  if (!imageUrl.value) {
    errorMessage.value = '请输入影像 URL';
    return;
  }
  if (!renderingEngine) {
    errorMessage.value = '渲染引擎未初始化';
    return;
  }

  isLoading.value = true;
  errorMessage.value = '';

  try {
    await nextTick();
    const viewport = renderingEngine.getStackViewport(viewportId);
    if (!viewport) throw new Error('找不到视口');

    const imageId = `wadouri:${imageUrl.value}`;
    await viewport.setStack([imageId]);
    viewport.resetCamera();
    renderingEngine.render();
  } catch (e: any) {
    console.error('加载影像失败:', e);
    errorMessage.value = `加载失败: ${e.message}`;
  } finally {
    isLoading.value = false;
  }
};

const resetViewport = () => {
  renderingEngine?.getStackViewport(viewportId)?.resetCamera();
  renderingEngine?.render();
  clearToolActivation();
  setActiveTool(PanTool.toolName, MouseBindings.Primary);
};

const activateWwwcTool = () => setActiveTool(WindowLevelTool.toolName, MouseBindings.Primary);
const activateZoomTool = () => setActiveTool(ZoomTool.toolName, MouseBindings.Wheel);
const activatePanTool = () => setActiveTool(PanTool.toolName, MouseBindings.Primary);
const activateLengthTool = () => setActiveTool(LengthTool.toolName, MouseBindings.Primary);
const activateProbeTool = () => setActiveTool(ProbeTool.toolName, MouseBindings.Primary);
const activateStackScrollTool = () => setActiveTool(StackScrollTool.toolName, MouseBindings.Primary);
const activateAngleTool = () => setActiveTool(AngleTool.toolName, MouseBindings.Primary);
const activateEllipseTool = () => setActiveTool(EllipticalROITool.toolName, MouseBindings.Primary);
const activateCircleROITool = () => setActiveTool(CircleROITool.toolName, MouseBindings.Primary);

const clearAllAnnotations = () => {
  clearAllToolState();
};

onMounted(() => {
  initializeCornerstone();
});

onUnmounted(() => {
  renderingEngine?.destroy();
  if (ToolGroupManager.getToolGroup(toolGroupId)) {
    ToolGroupManager.destroyToolGroup(toolGroupId);
  }
});
</script>

<style scoped>
#cornerstoneViewport {
  height: 600px;
}
.animate-spin {
  animation: spin 1s linear infinite;
}
@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}
.fade-enter-active, .fade-leave-active {
  transition: opacity 0.3s ease;
}
.fade-enter-from, .fade-leave-to {
  opacity: 0;
}
</style>
